#Copyright (c) 2012-8 Civa Lin. All rights reserved.
"""
Path Utility 路徑工具模組

本模組提供路徑的分析調整工具，是官方 os.path 模組的擴充。

本模組的變數命名方式：
    filename 表示完整檔案路徑
    dir 或 dirname 表示路徑
    base 表示主檔名
    ext 表示副檔名（含.）
    baseext 表示 base + ext
"""

import os
import os.path
import functools
import itertools
import sys


@functools.lru_cache()
def splitdbe(filename):
    '''取回給定檔名的：Dir路徑、Base主檔名、Ext副檔名（含.）'''
    dirname = os.path.dirname(filename)
    baseext = os.path.basename(filename)
    base, ext = os.path.splitext(baseext)
    return dirname, base, ext

@functools.lru_cache()
def joindbe(dir, base, ext):
    '''合併 dir base 與 ext 成為完整路徑'''
    filename = chext(base, ext)
    filepath = os.path.join(dir, filename)
    return filepath

@functools.lru_cache()
def norm(filename):
    '''取回給定檔名的標準化

        運用 os.path 的 normpath 與 normcase處理檔名。
        經本函式處理後，所有指向同一目標的路徑，將塌縮為唯一表述方式
        '''
    return os.path.normcase(os.path.normpath(filename))

def extof(filename):
    '''取得指定 filename 的副檔名（含.）'''
    base, ext = os.path.splitext(filename)
    return ext

def baseof(filename):
    '''取得指定 filename 的主檔名。

        如：「/home/xxx/text.txt」中的「text」
        '''
    dirname, base, ext = splitdbe(filename)
    return base

@functools.lru_cache()
def chbase(filename, newbase):
    '''變更 filename 的主檔名，並回傳。

        例如：
            >> chbase('/home/xxx/text.txt', 'game')
            '/home/xxx/game.txt'
            '''
    dirname, base, ext = splitdbe(filename)
    return os.path.join(dirname, newbase + ext)

@functools.lru_cache()
def chext(filename, newext):
    '''變更 filename 的副檔名，並回傳。

        newext 是以 os.extsep (.)開頭的新副檔名。
        如果第一個字元不是 os.extsep (.) ，則程式會自動添上。

        例如：
            >> chext('/home/xxx/text.txt', '.jpg')
            '/home/xxx/text.jpg'
            '''
    if not newext.startswith(os.extsep):
        newext = os.extsep + newext # 補上前綴點
    before, ext = os.path.splitext(filename)
    return before + newext

def chdir(filename, newdir):
    '''變更 filename 的路徑名，並回傳。

        例如：
            >> chdir('/home/xxx/text.txt', '~')
            '~/text.txt'
            '''
    baseext = os.path.basename(filename)
    return os.path.join(newdir, baseext)

def validof(baseext, platform = sys.platform):
    '''依據 baseext，產生與其對應的有效路徑名。

        具體說來，是會把無效的檔名字元濾掉或替換為有效字元，如：
            >> valid('test/?re.jpg')
            'test／？re.jpg'

        platform = sys.platform 定義的平台名稱字串（最少需包括前 3 個字元）
                   如 win, win32, darwin, linux, lin 等。
                   也可以輸入 all，這代表在內部有定義的所有平台下，檔名
                   都是安全可用的。

        return ==> 正確可用的檔名
        '''
    platform_key = platform[:3]
    trans = _validtrans()
    return baseext.translate(trans[platform_key])

@functools.lru_cache(None)
def _validtrans():
    '''產生供 validof() 使用的翻譯對照表'''
    def update_return(x, y):
        x.update(y)
        return x
    data = {'lin' : str.maketrans('/', '／', '\0\n'),
            'win' : str.maketrans('/\\?*:|"<>', '／＼？＊：｜”＜＞', '\0\n'),
            'dar' : str.maketrans(':', '：', '\0\n')}
    data['all'] = functools.reduce(
            update_return,
            itertools.chain(dict(), data.values()))
    return data
